package com.haodai.vip.tomcat.server;

import com.haodai.vip.tomcat.utils.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.BreakIterator;
import java.util.*;

/**
 * Created by huangtao on 17/5/27.
 */
public class Request {

    private String method;
    private String path;

    private Map<String, String> headerMap = new HashMap<>();
    private Map<String, Object> paramMap = new HashMap<>();

    private String fileSplitLine;
    private String host;

    private Cookie[] cookies;
    private String sessionId;

    public Request(InputStream input, OutputStream out) {
        parse(input, out);
    }

    public void parse(InputStream inputStream, OutputStream out) {
        String requestHeaderString = IOUtils.requestHeaderString(inputStream);   //获取请求行 和 请求头
        parseHeader(requestHeaderString);
//        if (path.endsWith("upLoadMaxFile.action")){
//            try {
//                out.write("开始上传".getBytes(Config.Encoding.ENCODE));
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
        int contentLength = getContentLength();
        if (contentLength > 0){
            if (Config.RequestInfo.CONTENT_TYPE_HAS_FILE.equalsIgnoreCase(getContentType())){  //包含文件
                Map<String, Object> formParamMap = IOUtils.requestFileContentString(inputStream, fileSplitLine);
                paramMap.putAll(formParamMap);
            } else { //不包含文件
                String requestContentString = IOUtils.requestContentString(inputStream, contentLength);
                parsePostParam(requestContentString);
            }
        }

        String cookieString = headerMap.get("Cookie");

        if (cookieString != null){
            headerMap.remove("Cookie");
            String[] cookieArray = cookieString.split(";");
            cookies = new Cookie[cookieArray.length];
            for (int i = 0; i < cookieArray.length; i++) {
                String[] split = cookieArray[i].split("=");
                String key = split[0];
                String value = split[1];
                cookies[i] = new Cookie(key, value);
                if ("JSESSIONID".equalsIgnoreCase(key)){
                    sessionId = value;
                }
            }
        }
    }

    private void parseHeader(String requestHeaderString) {
        if (requestHeaderString == null){
            return;
        }

        String[] requestArray = requestHeaderString.split("\\n");

        for (int i = 0; i < requestArray.length; i++) {
            String lineString = requestArray[i];
            if (i == 0){
                String line = lineString;
                String[] lineArray = line.split(" ");
                method = lineArray[0];
                path = lineArray[1];
                if (Config.Method.GET.equalsIgnoreCase(method)){
                    parseGetParam();
                }
            } else {
                String[] line = lineString.split(":");
                String name = line[0].trim();
                String value = line[1].trim();

                if (Config.RequestInfo.CONTENT_TYPE.equalsIgnoreCase(name)){
                    if (value.contains(";")){
                        String[] contentTypeArray = value.split(";");
                        fileSplitLine = contentTypeArray[1];
                        value = contentTypeArray[0];
                        fileSplitLine = fileSplitLine.substring(fileSplitLine.indexOf(Config.RequestInfo.BOUNDARY)+Config.RequestInfo.BOUNDARY.length()+1);
                    }
                }
                headerMap.put(name, value);
            }
        }
    }

    private void parseGetParam() {
        if (path.contains("?")){
            String[] pathSplit = path.split("\\?");
            path = pathSplit[0];
            String endString = pathSplit[1];
            String[] params = endString.split("&");
            for (int i = 0; i < params.length; i++) {
                String paramString = params[i];
                String[] param = paramString.split("=");
                String key = param[0];
                String value = param[1];
                paramMap.put(key, value);
            }
        }
    }

    private void parsePostParam(String posParamString) {
        String[] posParamsString = posParamString.split("&");
        for (int i = 0; i < posParamsString.length; i++) {
            String pos = posParamsString[i];
            String[] posParam = pos.split("=");
            paramMap.put(posParam[0].trim(), posParam[1].trim());
        }
    }

    public String getHeader(String name){
        return headerMap.get(name);
    }

    public Object getParam(String name){
        return paramMap.get(name);
    }

    public String getPath() {
        return path;
    }

    public String getMethod() {
        return method;
    }

    public List<String> getHeaderNames(){
        List<String> nameList = new ArrayList<>();
        for (Map.Entry<String, String> entry : headerMap.entrySet()){
            nameList.add(entry.getKey());
        }
        return nameList;
    }

    public List<String> getParamsNames(){
        List<String> nameList = new ArrayList<>();
        for (Map.Entry<String, Object> entry : paramMap.entrySet()){
            nameList.add(entry.getKey());
        }
        return nameList;
    }

    public String getContentType(){
        String contentType = headerMap.get(Config.RequestInfo.CONTENT_TYPE);
        if (contentType == null){
            return Config.RequestInfo.CONTENT_TYPE_NO_FILE;
        }
        return contentType;
    }

    public int getContentLength(){
        String contentLength = headerMap.get(Config.RequestInfo.CONTENT_LENGTH);
        if (contentLength == null){
            return 0;
        }
        return Integer.parseInt(contentLength);
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getHost() {
        return host;
    }

    public Cookie[] getCookies(){
        return cookies;
    }

    public HttpSession getSession(Response response){
        HttpSession httpSession;
        if (sessionId != null){
            httpSession = HttpServer.getInstance().sessionMap.get(sessionId);
            if (httpSession == null){
                httpSession = new HttpSession();
                HttpServer.getInstance().sessionMap.put(sessionId, httpSession);
            }
        } else {
            sessionId = UUID.randomUUID().toString();
            httpSession = new HttpSession();
            HttpServer.getInstance().sessionMap.put(sessionId, httpSession);
        }
        httpSession.sessionId = sessionId;
        response.addCookie("JSESSIONID", sessionId);
        return httpSession;
    }

}
